﻿using System;
using System.Collections;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.IO;
using InfoJetSoft.Service.Entity;
using InfoJetSoft.Service.Util;
using InfoJetSoft.Service.EscapeRule;

namespace InfoJetSoft.Service.Worker
{
	
	class FormBuildXMLDocByXMLWorker
	{
		
		public static void  buildXMLDocByXML(Form form, string xml)
		{
			FormBuildXMLDocByXMLWorker.buildXMLDoc(form, xml);

            //CID 0749 //2011.09.01 //Begin
            DigitalSignatureChecker.CheckSignature(form);
            //CID 0749 //2011.09.01 //End

			//将XmlDoc中的Namespace和Manifest中的Namespace统一.
			NamespaceUtil.unifyNamespaces( form.XmlDoc, form.Manifest );
			form.XmlNsResolver = new NamespaceResolver(form.XmlDoc);

			//根据InfoJetService.config中的ContextValue定义,更新Xml.
			FormConfigContextValue.UpdateWhileOpenXml( form );

			FormUtil.formatPiHref( form );

			//CID 0451 //2009.11.09 //Begin
			SchemaPSVI.clearXsiNil( form );
			//CID 0451 //2009.11.09 //End

			//CID 0167 //2008.12.16 //Begin
			ImportParameter.ExecuteOnOpen( form );
			//CID 0167 //2008.12.16 //End
			//CID 0159 //2008.12.03 //Begin
			form.JetContext.OnXmlDocumentReadyEvent( form );
			//CID 0159 //2008.12.03 //End
			form.JetContext.OnXmlDocumentCompletedEvent( form );
			ScriptControlContext.updateContext(form);
		}

		//这个函数也被FormBuildXMLDocByMergerWorker调用,用于构造用于合并的主文档.
		//也就是说,这里只对主文档进行升级.
		public static void buildXMLDoc(Form form, string xml)
        {
            //CID 1192 //2012.05.12 //Begin
            xml = System.Text.RegularExpressions.Regex.Replace(xml, "^[^<]", "");
            //CID 1192 //2012.05.12 //End
            //CID 1022 //2011.10.16 //Begin
            XmlDocument xmlDoc = null;
            if (form.Manifest.FormFieldsCacheEnabled)
            {
                xmlDoc = DOMUtil.buildDocPreserveWhitespace(System.Text.Encoding.UTF8.GetBytes(xml));
            }
            else
            {
                xmlDoc = DOMUtil.buildDoc(System.Text.Encoding.UTF8.GetBytes(xml));
            }
            //CID 1022 //2011.10.16 //End
			form.XmlDoc = xmlDoc;
			form.XmlNsResolver = new NamespaceResolver(xmlDoc);

			if( form.Manifest.Upgrade == null )
			{
				return;
			}
			if( form.Manifest.Upgrade.DoNothing )
			{
                //即使Nothing也要设置SolutionVersion.
                //CID 0802 //2011.02.23 //Begin
                UpdateSolutionVersion(form, xmlDoc);
                //CID 0802 //2011.02.23 //End
				return;
			}
			else if( form.Manifest.Upgrade.UseScript )
			{
				VersionCode docVersion = getSolutionVersion(xmlDoc);
				if ( docVersion.compare( form.Manifest.SolutionVersion ) < 0 && form.Manifest.Upgrade != null ) 
				{
					FormCodeDispatchWorker.OnVersionUpgrade( form, docVersion );
				}
				form.XmlNsResolver = new NamespaceResolver(form.XmlDoc);
				return;
			}
			else
			{
				VersionCode docVersion = getSolutionVersion(xmlDoc);
                if (docVersion == null)
                { 
                    //即使有Upgrade也不更新,但是要更新SolutionVersion.
                    //CID 0802 //2011.02.23 //Begin
                    UpdateSolutionVersion(form, xmlDoc);
                    //CID 0802 //2011.02.23 //End
                }
                else if ( docVersion.compare( form.Manifest.SolutionVersion ) < 0 ) 
				{
					XmlDocument upgradeDoc = form.Manifest.Upgrade.Doc;
					XslTransform xslt = new XslTransform();
                    //CID 0678 //2010.11.03 //Begin
                    xslt.Load(upgradeDoc.CreateNavigator());
                    //CID 0678 //2010.11.03 //End

                    //CID 0749 //2011.09.10 //Begin
                    XmlDocument inputDoc = new XmlDocument();
                    inputDoc.LoadXml(xml);
                    //CID 0749 //2011.09.10 //End

                    MemoryStream outputStream = new MemoryStream();
					XmlTextWriter writer = new XmlTextWriter( outputStream , System.Text.UTF8Encoding.UTF8 );

                    //CID 0678 //2010.11.03 //Begin
                    //CID 0749 //2011.09.10 //Begin
                    xslt.Transform(inputDoc, null, writer);
                    //CID 0749 //2011.09.10 //End
                    //CID 0678 //2010.11.03 //End
					outputStream.Seek( 0 , System.IO.SeekOrigin.Begin );

                    //CID 0749 //2011.09.10 //Begin
                    byte[] content = outputStream.ToArray();
                    xmlDoc = DOMUtil.buildDoc(content);
                    //CID 0749 //2011.09.10 //End

                    //CID 0802 //2011.02.23 //Begin
                    UpdateSolutionVersion(form, xmlDoc);
                    //CID 0802 //2011.02.23 //End
					form.XmlDoc = xmlDoc;
					form.XmlNsResolver = new NamespaceResolver(xmlDoc);
				}
				return;
			}
		}

        //CID 0802 //2011.02.23 //Begin
        private static void UpdateSolutionVersion(Form form, XmlDocument xmlDoc)
        {
            foreach (XmlNode node in xmlDoc.ChildNodes)
            {
                if (node is XmlProcessingInstruction)
                {
                    XmlProcessingInstruction pi = (XmlProcessingInstruction)node;
                    replaceSolutionVersion(pi, form.Manifest.SolutionVersion.Value());
                }
            }
        }
        //CID 0802 //2011.02.23 //End
		
		private static void replaceSolutionVersion( XmlProcessingInstruction pi, string newSolutionVersion ){
			string piValue = pi.Value;
			string SolutionVersionName = "solutionVersion=\"";
			string comma = "\"";
			int startIndex = piValue.IndexOf( SolutionVersionName );
			if( startIndex < 0 ){
				SolutionVersionName = "solutionVersion='";
				startIndex = piValue.IndexOf( SolutionVersionName );
				comma = "'";
			}
            if (startIndex >= 0)
            {
                int endIndex = piValue.IndexOf(comma, startIndex + SolutionVersionName.Length);
                if (startIndex < endIndex)
                {
                    String start = piValue.Substring(0, startIndex + SolutionVersionName.Length);
                    String end = piValue.Substring(endIndex);
                    String newPiValue = start + newSolutionVersion + end;
                    pi.Value = newPiValue;
                }
            }
            //CID 0802 //2011.02.23 //Begin
            else
            {
                if (pi.Value.EndsWith(" "))
                {
                    pi.Value = pi.Value + "solutionVersion=\"" + newSolutionVersion + "\" ";
                }
                else
                {
                    pi.Value = pi.Value + " solutionVersion=\"" + newSolutionVersion + "\" ";
                }
            }
            //CID 0802 //2011.02.23 //End
		}

		private static VersionCode getSolutionVersion(XmlDocument xmlDoc)
		{
			XmlNodeList nodeList = xmlDoc.ChildNodes;
			foreach (XmlNode node in nodeList)
			{
				if (node is XmlProcessingInstruction)
				{
					XmlProcessingInstruction pi = (XmlProcessingInstruction) node;
					if (pi.Name.Equals("mso-infoPathSolution"))
					{
						string value_Renamed = pi.Value;
						string solutionVersionValue = parseSolutionValue(value_Renamed);
                        //CID 0802 //2011.02.23 //Begin
                        if (solutionVersionValue.Length > 0)
                        {
                            return new VersionCode(solutionVersionValue);
                        }
                        else
                        {
                            return null;
                        }
                        //CID 0802 //2011.02.23 //End
					}
				}
			}
            //CID 0802 //2011.02.23 //Begin
            return null;
            //CID 0802 //2011.02.23 //End
		}
		
		private static string parseSolutionValue(string value_Renamed)
		{
			string attrValue = "";
			StringTokenizer tokenizer = new StringTokenizer(value_Renamed, " ");
			while (tokenizer.HasMoreElements())
			{
				string token = tokenizer.NextToken();
				if (token.IndexOf("solutionVersion=") == 0)
				{
					attrValue = token.Substring("solutionVersion=".Length);
					attrValue = attrValue.Replace("\"", "");
					attrValue = attrValue.Replace("'", "");
					break;
				}
				else if (token.Equals("solutionVersion"))
				{
					if (tokenizer.HasMoreTokens())
					{
						token = tokenizer.NextToken();
						if (token.Equals("="))
						{
							if (tokenizer.HasMoreTokens())
							{
								token = tokenizer.NextToken();
								attrValue = token;
								attrValue = attrValue.Replace("\"", "");
								attrValue = attrValue.Replace("'", "");
								break;
							}
							else
							{
								return "";
							}
						}
						else if (token.IndexOf("=") == 0)
						{
							attrValue = token.Substring(1);
							attrValue = attrValue.Replace("\"", "");
							attrValue = attrValue.Replace("'", "");
						}
						else
						{
							return "";
						}
					}
					else
					{
						return "";
					}
				}
			}
			return attrValue;
		}
	}
}